/*
 * syscalls.c: Kernel syscall implementations
 *
 * Author: Mike Kasick <mkasick@andrew.cmu.edu>
 * Date:   Sun, 14 Oct 2007 00:07:38 -0400
 */

#include <bits/errno.h>
#include <bits/fileno.h>
#include <exports.h>

/* Exits the kernel, never returns to user mode. */
void exit_syscall(int status) {
	exit_kernel(status);
}

/* An invalid syscall causes the kernel to exit. */
void invalid_syscall(void) {
	puts("Kernel panic: invalid syscall!\n");

	exit_kernel(0x0badc0de);
}

// swi_dispatch:  makes appropriate system calls based on swi_num
unsigned int swi_dispatch(unsigned swi_num, unsigned *regs) {
	unsigned int ret = 0;
	
	// make appropriate syscalls
	switch (swi_num) {
		case EXIT_SWI:
			//if (DEBUG) printf("EXIT_SWI: %x, %x\n", swi_num, (unsigned int)regs);
			exit(regs[0]);
			break;
			
		case READ_SWI:
			//if (DEBUG) printf("READ_SWI: %x, %x\n", swi_num, (unsigned int)regs);
			ret =  read(regs[0], (char *)(regs[1]), regs[2]);
			break;
			
		case WRITE_SWI:
			//if (DEBUG) printf("WRITE_SWI: %x, %x\n", swi_num, (unsigned int)regs);
			ret = write(regs[0], (char *)(regs[1]), regs[2]);
			break;
		
		case SLEEP_SWI:
			break;
			
		case TIME_SWI:
			break;
			
		default: invalid_syscall();
	}
	
	// store the return value in r0
	regs[0] = ret;
	
	//if (DEBUG) printf("returning from swi handler: %x\n", ret);
	return ret;
}
